package com.zhiche.lisa.lspm.service.driver.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zhiche.lisa.core.enums.DriverCheckinStatusEnum;
import com.zhiche.lisa.core.enums.FleetResourcesEnum;
import com.zhiche.lisa.core.enums.IntegrationEnum;
import com.zhiche.lisa.core.enums.TableStatusEnum;
import com.zhiche.lisa.core.enums.exception.DriverExceptionEnum;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.supports.RestfulResponse;
import com.zhiche.lisa.core.utils.Account.AccountUtil;
import com.zhiche.lisa.core.utils.Account.JwtAccountVO;
import com.zhiche.lisa.core.utils.HttpClientUtil;
import com.zhiche.lisa.core.utils.geo.util.GeoUtil;
import com.zhiche.lisa.core.utils.geo.util.Point;
import com.zhiche.lisa.lspm.config.LspmProperties;
import com.zhiche.lisa.lspm.controller.DriverController;
import com.zhiche.lisa.lspm.dao.mapper.driver.DriverCheckinMapper;
import com.zhiche.lisa.lspm.dao.model.carrier.bo.CarrierInfoBO;
import com.zhiche.lisa.lspm.dao.model.carrier.bo.VehicleQueueBO;
import com.zhiche.lisa.lspm.dao.model.driver.Driver;
import com.zhiche.lisa.lspm.dao.model.driver.DriverCheckin;
import com.zhiche.lisa.lspm.dao.model.driver.DriverCheckinLine;
import com.zhiche.lisa.lspm.dao.model.driver.DriverCheckinStatus;
import com.zhiche.lisa.lspm.dao.model.driver.bo.DriverCheckinBO;
import com.zhiche.lisa.lspm.dao.model.driver.bo.DriverCheckinLineBO;
import com.zhiche.lisa.lspm.dao.model.fleet.Fleet;
import com.zhiche.lisa.lspm.dao.model.lsp.LspInfo;
import com.zhiche.lisa.lspm.dao.model.trailer.bo.TrailerInfoBO;
import com.zhiche.lisa.lspm.dto.DriverCheckinDTO;
import com.zhiche.lisa.lspm.service.carrier.ICarrierInfoService;
import com.zhiche.lisa.lspm.service.driver.IDriverCheckinLineService;
import com.zhiche.lisa.lspm.service.driver.IDriverCheckinService;
import com.zhiche.lisa.lspm.service.driver.IDriverCheckinStatusService;
import com.zhiche.lisa.lspm.service.driver.IDriverService;
import com.zhiche.lisa.lspm.service.fleet.IFleetBindService;
import com.zhiche.lisa.lspm.service.fleet.IFleetService;
import com.zhiche.lisa.lspm.service.lsp.LspInfoService;
import com.zhiche.lisa.lspm.service.trailer.TrailerInfoService;
import com.zhiche.lisa.lspm.service.utils.*;
import com.zhiche.lisa.lspm.vo.common.AccountVO;
import com.zhiche.lisa.lspm.vo.common.TransportationTypeVO;
import com.zhiche.lisa.lspm.vo.driver.*;
import com.zhiche.lisa.lspm.vo.fleet.FleetBindVO;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.joda.time.DateTime;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 司机报班记录 service impl
 *
 * @author lbl
 * @since 2018-05-31
 */
@Service
public class DriverCheckinServiceImpl extends ServiceImpl<DriverCheckinMapper, DriverCheckin>
        implements IDriverCheckinService {

    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DriverController.class);

    @Autowired
    private IDriverCheckinStatusService driverCheckinStatusService;
    @Autowired
    private ICarrierInfoService carrierInfoService;
    @Autowired
    private TrailerInfoService trailerInfoService;
    @Autowired
    private LspmProperties properties;
    @Autowired
    private IDriverService driverService;
    @Autowired
    private ErpUtil erpUtil;
    @Autowired
    private IDriverCheckinLineService driverCheckinLineService;
    @Autowired
    private IDriverCheckinService driverCheckinService;
    @Autowired
    private MdmUtil mdmUtil;
    @Autowired
    private UaaUtil uaaUtil;
    @Autowired
    private IntegrationUtil integrationUtil;
    @Autowired
    private IFleetService fleetService;
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private LspInfoService lspInfoService;

    @Autowired
    private IFleetBindService fleetBindService;

    private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Value("${integrationToOtm}")
    private String integrationToOtm;
    @Value("${devop.getProvinceByCodeUrl}")
    private String getProvinceByCodeUrl;
    @Value("${devop.url}")
    private String devopUrl;
    @Value("${devop.socketTimeout}")
    private Integer socketTimeout;
    @Value("${integration.checkinToOtmLog}")
    private String checkinToOtmLog;
    @Value("${integration.url}")
    private String integrationUrl;

    @Override
    public Page<DriverCheckinLineVO> driverCheckinLine(Page<DriverCheckinLineBO> page) {
        page.setOrderByField("gmtCheckin");
        page.setAsc(false);
        List<DriverCheckinLineVO> list = baseMapper.driverCheckinLine(page,
                buildCondition(page.getCondition()));
        Page<DriverCheckinLineVO> pageVo = new Page<>();
        BeanUtils.copyProperties(page, pageVo);
//        list.forEach(driverCheckinLineVO -> {
//            Long carrierId = driverCheckinLineVO.getCarrierId();
//            CarrierInfo carrierInfo = carrierInfoService.selectById(carrierId);
//            if (Objects.nonNull(carrierInfo)) {
//                driverCheckinLineVO.setCarrierPlate(carrierInfo.getPlate());
//            }
//            Long trailerId = driverCheckinLineVO.getTrailerId();
//            TrailerInfo trailerInfo = trailerInfoService.selectById(trailerId);
//            if (Objects.nonNull(trailerInfo)) {
//                driverCheckinLineVO.setTrailerPlate(trailerInfo.getPlate());
//            }
//        });
        pageVo.setRecords(list);
        return pageVo;
    }

    @Override
    public Page<DriverCheckinLineVO> driverCancelCheckinLine(Page<DriverCheckinLineBO> page) {
        page.setOrderByField("gmtCheckin").setAsc(false);
        List<DriverCheckinLineVO> list = baseMapper.driverCancelCheckinLine(page,
                buildCondition(page.getCondition()));
        Page<DriverCheckinLineVO> pageVo = new Page<>();
        BeanUtils.copyProperties(page, pageVo);
        pageVo.setRecords(list);
        return pageVo;
    }

    @Transactional
    @Override
    public Boolean authDriverCheckIn(Integer[] driverCheckIds, String authorization) throws BaseException {
        Boolean blnRtn = false;
        List<Integer> listIds = Arrays.asList(driverCheckIds);
        try {
            EntityWrapper<DriverCheckinStatus> ew = new EntityWrapper<>();
            ew.in("checkin_id", listIds);
            List<DriverCheckinStatus> lists = driverCheckinStatusService.selectList(ew);
            lists.forEach(driverCheckinStatus -> driverCheckinStatus.setCheckinStatus("20"));
            driverCheckinStatusService.updateBatchById(lists);
            lists.forEach(driverCheckinStatus -> {
                //写入到取消报班记录写入到ERP中
                //erpUtil.pushCancelCheckin(driverCheckinStatus.getCheckinId());

                //同步取消报班记录到otm中
                IntegrationOtm(driverCheckinStatus.getCheckinId(), authorization);

            });
            blnRtn = true;
        } catch (Exception ex) {
            throw new BaseException(-1, ex.getMessage());
        }
        return blnRtn;
    }

    private void IntegrationOtm(Long id, String authorization) {
        if (IntegrationEnum.EXPORT.getCode().equals(IntegrationUtil.getIntegrationToOtm())) {
            DriverCheckinDTO driverCheckinDTO = driverCheckinService.getDriverCheckinById(id);
            // 转换车队类型
            String fleetTypeId = driverCheckinDTO.getFleetTypeId();
            if (TableStatusEnum.STATUS_1.getCode().equals(fleetTypeId)) {
                driverCheckinDTO.setFleetTypeId("y");
            }

            if (!StringUtils.isEmpty(driverCheckinDTO.getTrailerTypeId())) {
                TransportationTypeVO transportTypeByCode = mdmUtil.getTransportTypeByCode(driverCheckinDTO.getTrailerTypeId());
                driverCheckinDTO.setTrailerTypeName(integrationUtil.getTrailerTypeName(transportTypeByCode.getValue()));
                driverCheckinDTO.setTransMode(driverCheckinDTO.getTrailerTypeName());
            }
            integrationUtil.exportCheckin(driverCheckinDTO);
        }
    }

    private void IntegrationOtmNoTenant(Long id, String authorization) {
        if (IntegrationEnum.EXPORT.getCode().equals(IntegrationUtil.getIntegrationToOtm())) {
            DriverCheckinDTO driverCheckinDTO = driverCheckinService.getDriverCheckinByIdNoTenant(id);
            List<AccountVO> listTenantAccounts = uaaUtil.getListTenantAccount(1l, authorization);
            LOGGER.info("DriverCheckinServiceImpl.IntegrationOtmNoTenant.listTenantAccounts result {} ", listTenantAccounts);
            if (driverCheckinDTO.getFleetId() != null) {
                Fleet fleet = fleetService.selectByIdNoTenant(driverCheckinDTO.getFleetId());
                if (fleet != null && CollectionUtils.isNotEmpty(listTenantAccounts)) {
                    for (AccountVO accountVO : listTenantAccounts) {
                        if (Objects.nonNull(accountVO.getId()) && !StringUtils.isEmpty(fleet.getCreator())) {
                            if (accountVO.getId().toString().equals(fleet.getCreator())) {
                                driverCheckinDTO.setFleetId(fleet.getId());
                                break;
                            }
                        }
                        driverCheckinDTO.setFleetId(null);
                    }
                }
            }
            if (!StringUtils.isEmpty(driverCheckinDTO.getTrailerTypeId())) {
                TransportationTypeVO transportTypeByCode = mdmUtil.getTransportTypeByCode(driverCheckinDTO.getTrailerTypeId());
                driverCheckinDTO.setTrailerTypeName(integrationUtil.getTrailerTypeName(transportTypeByCode.getValue()));
                driverCheckinDTO.setTransMode(driverCheckinDTO.getTrailerTypeName());
            }
            integrationUtil.exportCheckin(driverCheckinDTO);
        }
    }

    @Override
    public List<DriverCheckin> getDriverCheckin36HoursNoTenant() throws Exception {
        DateTime dateTime = new DateTime();
        DateTime dtHours = dateTime.minusHours(36);
        return baseMapper.getDriverCheckinNoTenant(dtHours.toString(STANDARD_FORMAT), DriverCheckinStatusEnum.NOT_ARRANGED.getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCheckinStatus(Long checkinId, String status) throws BaseException {
        DriverCheckin driverCheckin = baseMapper.selectByIdNoTenant(checkinId);
        if (Objects.isNull(driverCheckin)) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getCode(),
                    DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getText());
        }
        EntityWrapper<DriverCheckinStatus> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("checkin_id", checkinId);
        DriverCheckinStatus driverCheckinStatus = new DriverCheckinStatus();
        driverCheckinStatus.setCheckinStatus(status);
        driverCheckinStatusService.update(driverCheckinStatus, entityWrapper);
        // 取消报班推送到OTM
        if (IntegrationEnum.EXPORT.getCode().equals(properties.getIntegrationToOtm())) {
            LOGGER.info("定时任务推送失效任务到OTM --chekinId:{}", checkinId);
            String token = tokenUtil.getTenantToken("tech-" + driverCheckin.getTenantId());
            IntegrationOtmNoTenant(checkinId, token);
        }
        //写入到取消报班记录写入到ERP中
        if (IntegrationEnum.EXPORT.getCode().equals(properties.getPushDataToERP())) {
            LOGGER.info("定时任务推送失效任务到ERP --chekinId:{}", checkinId);
            //erpUtil.pushCancelCheckin(driverCheckin.getId());
        }
    }

    @Override
    public List<DriverCheckin> selectByNowDayNoTenant(Long driverId) {
        return baseMapper.selectByNowDayNoTenant(driverId);
    }

    @Override
    public Page<DriverCheckinVO> getChekin(Page<DriverCheckinBO> page) {
        if (page == null) return null;
        Wrapper ew = whereCheckIn(page);
        List<DriverCheckinBO> listBO = baseMapper.selectCheckinListNoTenant(page, ew);
        List<DriverCheckinVO> listVO = Lists.newArrayList();
        Page<DriverCheckinVO> pageVo = new Page<>();
        BeanUtils.copyProperties(page, pageVo);
        listBO.forEach(driverCheckinBO -> {
            DriverCheckinVO driverCheckinVO = new DriverCheckinVO();
            BeanUtils.copyProperties(driverCheckinBO, driverCheckinVO);
            listVO.add(driverCheckinVO);
        });
        pageVo.setRecords(listVO);
        return pageVo;
    }

    private EntityWrapper<DriverCheckinBO> whereCheckIn(Page<DriverCheckinBO> page) {
        EntityWrapper<DriverCheckinBO> ew = new EntityWrapper();

        if (Objects.nonNull(page.getCondition()) && Objects.nonNull(page.getCondition().get("driverId"))) {
            ew.eq("driver_id", page.getCondition().get("driverId").toString().trim());
        }
        ew.orderBy("gmt_create", false);
        return ew;
    }

    @Override
    @Transactional
    public void cancelChekin(DriverCheckinBO driverCheckinBO, String authorization) throws BaseException {
        if (Objects.isNull(driverCheckinBO.getId())) {
            throw new BaseException("取消报班Id不能为空");
        }
        if (Objects.isNull(driverCheckinBO.getDriverId())) {
            throw new BaseException("取消申请DriverId不能为空");
        }
        DriverCheckin driverCheckin = this.selectById(driverCheckinBO.getId());
        if (Objects.isNull(driverCheckin)) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getCode(), DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getText());
        }
        if (!driverCheckin.getDriverId().equals(driverCheckinBO.getDriverId())) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CHEKIN_CANCEL_NO_PERMISSIONS.getCode(), DriverExceptionEnum.DRIVER_CHEKIN_CANCEL_NO_PERMISSIONS.getText());
        }
        DriverCheckinStatus driverCheckinStatus = driverCheckinStatusService.selectByCheckinId(driverCheckinBO.getId());
        if (!DriverCheckinStatusEnum.NOT_ARRANGED.getCode().equals(driverCheckinStatus.getCheckinStatus())) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getCode(), DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getText());
        }
        driverCheckinStatus.setComment(driverCheckinBO.getComment());
        driverCheckinStatus.setCheckinStatus(DriverCheckinStatusEnum.CANCEL_APPLY.getCode());
        driverCheckinStatusService.updateById(driverCheckinStatus);
        IntegrationOtm(driverCheckinBO.getId(), authorization);
    }

    @Override
    @Transactional
    public void otmCancelChekin(OtmCheckinVO otmCheckinVO) throws BaseException {

        DriverCheckin driverCheckin = baseMapper.getDriverCheckinByIdNotenant(Long.valueOf(otmCheckinVO.getCheckinId()));
        if (Objects.isNull(driverCheckin)) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getCode(), DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getText());
        }
        DriverCheckinStatus driverCheckinStatus = driverCheckinStatusService.selectByCheckinIdNotenant(Long.valueOf(otmCheckinVO.getCheckinId()));
        if (!DriverCheckinStatusEnum.NOT_ARRANGED.getCode().equals(driverCheckinStatus.getCheckinStatus())) {
            throw new BaseException(DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getCode(), DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getText());
        }
        driverCheckinStatus.setComment(otmCheckinVO.getRevokeReason());
        driverCheckinStatus.setCheckinStatus(DriverCheckinStatusEnum.CANCEL.getCode());
        driverCheckinStatusService.updateById(driverCheckinStatus);
    }

    /**
     * 直接取消报班（不审核）
     */
    @Override
    @Transactional
    public void checkInNonAudited(DriverCheckinBO driverCheckinBO, String authorization) {
        try {
            DriverCheckin driverCheckin = this.selectById(driverCheckinBO.getId());
            if (Objects.isNull(driverCheckin)) {
                throw new BaseException(DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getCode(), DriverExceptionEnum.DRIVER_CHEKIN_INFO_NOT_EXIST.getText());
            }
            DriverCheckinStatus driverCheckinStatus = driverCheckinStatusService.selectByCheckinId(driverCheckinBO.getId());
            if (!DriverCheckinStatusEnum.NOT_ARRANGED.getCode().equals(driverCheckinStatus.getCheckinStatus())) {
                throw new BaseException(DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getCode(), DriverExceptionEnum.DRIVER_CANCEL_CHECKIN_ERROR.getText());
            }
            //更新报班的状态信息
            driverCheckinStatus.setComment(driverCheckinBO.getComment());
            driverCheckinStatus.setCheckinStatus(DriverCheckinStatusEnum.CANCEL.getCode());
            driverCheckinStatusService.updateById(driverCheckinStatus);
            //同步erp
            //erpUtil.pushCancelCheckin(driverCheckin.getId());

            //同步取消报班记录到otm中
            IntegrationOtm(driverCheckinStatus.getCheckinId(), authorization);

        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkin(DriverCheckinBO driverCheckinBO, String authorization) throws BaseException {

        // 查询司机信息
        Driver driver = driverService.selectById(driverCheckinBO.getDriverId());
        if (driver == null) {
            throw new BaseException("无法找到对应的司机信息");
        }
        //查询承运商是否被禁用
        LspInfo lspInfo = lspInfoService.selectLspInfoByDriverId(driverCheckinBO.getDriverId());
        if (lspInfo.getStatus()==0){
            throw new BaseException("承运商已被禁用");
        }
        //查询司机报班重复
        List<DriverCheckin> list = this.selectByNowDayNoTenant(driverCheckinBO.getDriverId());
        if (!org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
            DriverCheckin driverCheckin = list.get(0);
            throw new BaseException("司机"+driver.getName()+"存在报班信息id:"+driverCheckin.getId());
        }
        // 查询是否有车队
        String fleetName = getFleetNameByDriver(driver.getId());
        //查询车队是否被禁用
        if (!StringUtils.isEmpty(fleetName)) {
            Wrapper<Fleet> ew = new EntityWrapper<>();
            ew.eq("fleet_name", fleetName);
            Fleet fleet = fleetService.selectOne(ew);
            if (!Objects.isNull(fleet) && fleet.getIsDelete() == 1) {
                throw new BaseException("车队已被禁用");
            }
        }
        // 查询牵引车信息
        CarrierInfoBO carrierInfoBO = carrierInfoService.selectByDriverId(driverCheckinBO.getDriverId());
        if (Objects.isNull(carrierInfoBO)) {
            throw new BaseException("请先完善牵引车车信息");
        }
        // 查询挂车信息
        TrailerInfoBO trailerInfoBO = trailerInfoService.selectByCarrierInfoId(carrierInfoBO.getId());
        if (Objects.isNull(trailerInfoBO)) {
            throw new BaseException("请先完善挂车信息");
        }
        if (StringUtils.isEmpty(trailerInfoBO.getTrailerType())) {
            throw new BaseException("请先填写挂车类型");
        }
        //经纬度
        if (Objects.isNull(driverCheckinBO.getCheckinLatitude()) || Objects.isNull(driverCheckinBO.getCheckinLongtitude())) {
            throw new BaseException("没有获取经纬度信息");
        }
        //省市
        if (org.apache.commons.lang3.StringUtils.isBlank(driverCheckinBO.getCity()) &&
                org.apache.commons.lang3.StringUtils.isBlank(driverCheckinBO.getProvince())) {
            LOGGER.error("省市位置:city:{},province:{}", driverCheckinBO.getCity(),
                    driverCheckinBO.getProvince());
            throw new BaseException("没有获取地理位置信息");
        }

        DriverCheckin driverCheckin = new DriverCheckin();
        BeanUtils.copyProperties(driverCheckinBO, driverCheckin);
        driverCheckin.setLspId(driver.getLspId());
        driverCheckin.setGmtCreate(new Date());
        driverCheckin.setGmtCheckin(new Date());
        driverCheckin.setCarrierId(carrierInfoBO.getId());
        driverCheckin.setTrailerId(trailerInfoBO.getId());

        DriverCheckinStatus driverCheckinStatus = new DriverCheckinStatus();
        driverCheckinStatus.setCheckinStatus(DriverCheckinStatusEnum.NOT_ARRANGED.getCode());

        //加入创建人
        JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
        if (Objects.nonNull(jwtAccountVO)) {
            String accountId = jwtAccountVO.getAccountId();
            driverCheckin.setCreator(accountId);
            driverCheckinStatus.setCreator(accountId);
            driverCheckin.setTenantId(driver.getTenantId());
            driverCheckinStatus.setTenantId(driver.getTenantId());
        }

        //转化为标准的GPS
        Point point = new Point(driverCheckinBO.getCheckinLongtitude(), driverCheckinBO.getCheckinLatitude());
        Point src_ = GeoUtil.convertMars2Earth(point);

        driverCheckin.setCheckinLatitude(new BigDecimal(src_.getLat()));
        driverCheckin.setCheckinLongtitude(new BigDecimal(src_.getLon()));
        driverCheckinBO.setCheckinLatitude(src_.getLat());
        driverCheckinBO.setCheckinLongtitude(src_.getLon());

        this.insert(driverCheckin);
        driverCheckinStatus.setCheckinId(driverCheckin.getId());
        driverCheckinStatusService.insert(driverCheckinStatus);

        //写入报班明细,为导入OTM做准备
        //目的区域
        if (CollectionUtils.isNotEmpty(driverCheckinBO.getDestArray())) {
            driverCheckinBO.getDestArray().forEach(driverCheckinDestinationVO -> {
                //写入司机报班明细
                DriverCheckinLine driverCheckinLine = new DriverCheckinLine();
                driverCheckinLine.setDepartCity(driverCheckinBO.getDepartCity());
                driverCheckinLine.setDepartCityCode(driverCheckinBO.getDepartCityCode());
                driverCheckinLine.setDepartProvince(driverCheckinBO.getDepartProvince());
                driverCheckinLine.setDepartProvinceCode(driverCheckinBO.getDepartProvinceCode());
                if (driverCheckinDestinationVO.getCityLevel().equals("2")) {
                    List<NameValuePair> headNamePairs = Lists.newArrayList();
                    headNamePairs.add(new BasicNameValuePair("Authorization", authorization));
                    List<NameValuePair> pramsNamePairs = Lists.newArrayList();
                    pramsNamePairs.add(new BasicNameValuePair("code", driverCheckinDestinationVO.getCityParentCode()));
                    String result = HttpClientUtil.get(devopUrl + getProvinceByCodeUrl, headNamePairs, pramsNamePairs, socketTimeout);
                    JSONObject jsonObject = JSONObject.parseObject(result).getJSONObject("data");
                    CityVO cityVO = jsonObject.toJavaObject(CityVO.class);
                    driverCheckinLine.setDestProvince(cityVO.getAmapLabel());
                    driverCheckinLine.setDestCity(driverCheckinDestinationVO.getCityName());
                    driverCheckinLine.setDestCityCode(driverCheckinDestinationVO.getCityCode());
                    driverCheckinLine.setDestProvinceCode(driverCheckinDestinationVO.getCityParentCode());
                } else {
                    driverCheckinLine.setDestProvince(driverCheckinDestinationVO.getCityName());
                    driverCheckinLine.setDestProvinceCode(driverCheckinDestinationVO.getCityCode());
                }
                driverCheckinLine.setCheckinId(driverCheckin.getId());
                //始发区域
                String departRegion = driverCheckinBO.getDepartRegion();
                driverCheckinLine.setDepartAddress(departRegion);
                driverCheckinLine.setDestAddress(driverCheckinDestinationVO.getCityName());
                driverCheckinLine.setCreator(jwtAccountVO.getAccountId());
                driverCheckinLineService.insert(driverCheckinLine);
            });
        }

        VehicleQueueBO vehicleQueueBO = new VehicleQueueBO();

        // 司机公众号报班 id
        vehicleQueueBO.setDriverQueueId(driverCheckin.getId());
        // 司机名称
        vehicleQueueBO.setDriverName(driver.getName());
        // 车牌号
        vehicleQueueBO.setLicense(carrierInfoBO.getPlate());

        // 报到城市
        vehicleQueueBO.setDepartRegion(driverCheckinBO.getDepartRegion());

        //预计发运方向
        vehicleQueueBO.setDestRegion(driverCheckinBO.getDestRegion());

        //预计到达时间
        vehicleQueueBO.setGmtExpLoad(driverCheckinBO.getGmtExpLoad());

        // 报班时位置
        vehicleQueueBO.setLocation(driverCheckinBO.getCheckinAddr());

        //预计装载台数
        vehicleQueueBO.setAmtExp(driverCheckinBO.getAmtExp());

        //纬度
        vehicleQueueBO.setCheckinLatitude(driverCheckinBO.getCheckinLatitude());

        //经度
        vehicleQueueBO.setCheckinLongtitude(driverCheckinBO.getCheckinLongtitude());

        //fix 增加运力平台的车队和ERP车队校验
        vehicleQueueBO.setFleetName(fleetName);

        //推送报班记录到ERP
        erpUtil.pushCheckin(vehicleQueueBO);

        //司机报班推送OTM
        IntegrationOtm(driverCheckin.getId(), authorization);

        //写一条在途信息到ERP
        if (IntegrationEnum.EXPORT.getCode().equals(properties.getPushDataToERP())) {
            try {
                positionUpload(driverCheckinBO);
            } catch (Exception e) {
                LOGGER.info("位置推送ERP出错：" + e.getMessage());
            }
        }
    }

    private String getFleetNameByDriver(Long driverId) {
        EntityWrapper<FleetBindVO> ew = new EntityWrapper<>();
        ew.eq("resource_id", driverId)
                .eq("resource_type", FleetResourcesEnum.DRIVER.getCode())
                .orderBy("id", false);
        List<FleetBindVO> carrierFleetS = fleetBindService.queryBindDriverList(ew);
        if (CollectionUtils.isEmpty(carrierFleetS)) {
            // 新车队规则为空查老车队与牵引车绑定车队规则
            DriverToErpVO driverVO = driverService.driverFleetByCarrier(driverId);
            if (null == driverVO || null == driverVO.getNewFleetId()) {
                throw new BaseException("无法找到司机对应的车队信息");
            } else {
                return driverVO.getFleetName();
            }
        } else {
            return carrierFleetS.get(0).getFleetName();
        }
    }

    @Override
    public DriverCheckinDTO getDriverCheckinById(Long checkinId) {
        return baseMapper.getDriverCheckinById(checkinId);
    }

    /**
     * 分页查询报班信息 pc
     */
    @Override
    @Transactional(readOnly = true)
    public Page<DriverCheckinDTO> queryCheckinList(Page<DriverCheckinDTO> page) {
        if (page == null) {
            throw new BaseException("page参数不能为空");
        }
        Map<String, Object> cn = page.getCondition();
        EntityWrapper<DriverCheckinDTO> ew = new EntityWrapper<>();
        if (cn != null && !cn.isEmpty()) {
            buildCondition(cn, ew);
        }
        ew.orderBy("id", false);
        List<DriverCheckinDTO> data = baseMapper.queryCheckinPage(page, ew);
        page.setRecords(data);
        return page;
    }

    /**
     * 车辆报班 不含在途信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertNewCheckIn(DriverCheckinDTO dto, String token) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        if (dto.getDriverId() == null) {
            throw new BaseException("司机id不能为空");
        }
        if (StringUtils.isBlank(dto.getDepartRegion())) {
            throw new BaseException("意向启运地不能为空");
        }
        if (StringUtils.isBlank(dto.getDestRegion())) {
            throw new BaseException("意向目的地不能为空");
        }
        if (StringUtils.isBlank(dto.getDriverName())) {
            throw new BaseException("司机名称不能为空");
        }
        // 查询司机信息
        Driver driver = driverService.selectById(dto.getDriverId());
        if (driver == null) {
            throw new BaseException("未查询到司机的信息");
        }
        // 校验司机认证
        if(0 == driver.getAuthStatus() || 1 == driver.getIsDelete()){
            throw new BaseException("司机未认证或已删除！");
        }
        // 查询是否有车队
        String fleetName = getFleetNameByDriver(driver.getId());
        //查询车队是否被禁用
        if (!StringUtils.isEmpty(fleetName)) {
            Wrapper<Fleet> ew = new EntityWrapper<>();
            ew.eq("fleet_name", fleetName);
            Fleet fleet = fleetService.selectOne(ew);
            if (!Objects.isNull(fleet) && fleet.getIsDelete() == 1) {
                throw new BaseException("车队已被禁用");
            }
        }
        //查询司机报班重复
        List<DriverCheckin> list = this.selectByNowDayNoTenant(driver.getId());
        if (!org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
            DriverCheckin driverCheckin = list.get(0);
            throw new BaseException("司机"+driver.getName()+"存在报班信息id:"+driverCheckin.getId());
        }
        // 查询牵引车信息
        CarrierInfoBO carrierInfoBO = carrierInfoService.selectByDriverId(driver.getId());
        if (Objects.isNull(carrierInfoBO)) {
            throw new BaseException("请先完善牵引车车信息");
        }
        //查询承运商是否被禁用
        LspInfo lspInfo=lspInfoService.selectLspInfo(dto.getLspId());
        if (lspInfo.getStatus()==0){
            throw new BaseException("承运商已被禁用");
        }
        // 查询挂车信息
        TrailerInfoBO trailerInfoBO = trailerInfoService.selectByCarrierInfoId(carrierInfoBO.getId());
        if (Objects.isNull(trailerInfoBO)) {
            throw new BaseException("未查询到牵引车对应挂车信息");
        }

        if (StringUtils.isEmpty(trailerInfoBO.getTrailerType())) {
            throw new BaseException("请先填写挂车类型");
        }
        DriverCheckin driverCheckin = new DriverCheckin();
        driverCheckin.setDriverId(driver.getId());
        driverCheckin.setLspId(driver.getLspId());
        driverCheckin.setDepartRegion(dto.getDepartRegion());
        driverCheckin.setDestRegion(dto.getDestRegion());
        driverCheckin.setGmtCreate(new Date());
        driverCheckin.setGmtCheckin(new Date());
        driverCheckin.setGmtExpLoad(StringUtils.isBlank(dto.getExpLoadTime()) ? new Date() : new Date(Long.valueOf(dto.getExpLoadTime())));
        driverCheckin.setAmtExp(dto.getAmtExp());
        driverCheckin.setCarrierId(carrierInfoBO.getId());
        driverCheckin.setTrailerId(trailerInfoBO.getId());

        DriverCheckinStatus driverCheckinStatus = new DriverCheckinStatus();
        driverCheckinStatus.setCheckinStatus(DriverCheckinStatusEnum.NOT_ARRANGED.getCode());

        //加入创建人
        JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
        if (Objects.nonNull(jwtAccountVO)) {
            String accountId = jwtAccountVO.getAccountId();
            driverCheckin.setCreator(accountId);
            driverCheckinStatus.setCreator(accountId);
            // fix  调整中联管理员为下属公司报班时的tenantid取车辆的tenantId
            driverCheckin.setTenantId(driver.getTenantId());
            driverCheckinStatus.setTenantId(driver.getTenantId());
        }

        this.insert(driverCheckin);
        driverCheckinStatus.setCheckinId(driverCheckin.getId());
        driverCheckinStatusService.insert(driverCheckinStatus);

        //写入报班明细,为导入OTM做准备
        //目的区域
        if (CollectionUtils.isNotEmpty(dto.getDestArray())) {
            dto.getDestArray().forEach(driverCheckinDestinationVO -> {
                //写入司机报班明细
                DriverCheckinLine driverCheckinLine = new DriverCheckinLine();
                driverCheckinLine.setDepartCity(dto.getDepartRegion());
                driverCheckinLine.setDepartCityCode(dto.getDepartCityCode());
                driverCheckinLine.setDepartProvince(dto.getDepartProvince());
                driverCheckinLine.setDepartProvinceCode(dto.getDepartProvinceCode());
                if (driverCheckinDestinationVO.getCityLevel().equals("2")) {
                    List<NameValuePair> headNamePairs = Lists.newArrayList();
                    headNamePairs.add(new BasicNameValuePair("Authorization", token));
                    List<NameValuePair> pramsNamePairs = Lists.newArrayList();
                    pramsNamePairs.add(new BasicNameValuePair("code", driverCheckinDestinationVO.getCityParentCode()));
                    String result = HttpClientUtil.get(devopUrl + getProvinceByCodeUrl, headNamePairs, pramsNamePairs, socketTimeout);
                    JSONObject jsonObject = JSONObject.parseObject(result).getJSONObject("data");
                    CityVO cityVO = jsonObject.toJavaObject(CityVO.class);
                    driverCheckinLine.setDestProvince(cityVO.getAmapLabel());
                    driverCheckinLine.setDestCity(driverCheckinDestinationVO.getCityName());
                    driverCheckinLine.setDestCityCode(driverCheckinDestinationVO.getCityCode());
                    driverCheckinLine.setDestProvinceCode(driverCheckinDestinationVO.getCityParentCode());
                } else {
                    driverCheckinLine.setDestProvince(driverCheckinDestinationVO.getCityName());
                    driverCheckinLine.setDestProvinceCode(driverCheckinDestinationVO.getCityCode());
                }
                driverCheckinLine.setCheckinId(driverCheckin.getId());
                //始发区域
                String departRegion = dto.getDepartRegion();
                driverCheckinLine.setDepartAddress(departRegion);
                driverCheckinLine.setDestAddress(driverCheckinDestinationVO.getCityName());
                driverCheckinLine.setCreator(jwtAccountVO.getAccountId());
                driverCheckinLineService.insert(driverCheckinLine);
            });
        }

        VehicleQueueBO vehicleQueueBO = new VehicleQueueBO();

        // 司机公众号报班 id
        vehicleQueueBO.setDriverQueueId(driverCheckin.getId());
        // 司机名称
        vehicleQueueBO.setDriverName(driver.getName());
        // 车牌号
        vehicleQueueBO.setLicense(carrierInfoBO.getPlate());

        // 报到城市
        vehicleQueueBO.setDepartRegion(dto.getDepartRegion());

        //预计发运方向
        vehicleQueueBO.setDestRegion(dto.getDestRegion());

        //预计到达时间
        vehicleQueueBO.setGmtExpLoad(driverCheckin.getGmtExpLoad());

        //预计装载台数
        vehicleQueueBO.setAmtExp(dto.getAmtExp());

        // 报班时位置
        vehicleQueueBO.setLocation(dto.getDestRegion());

        //纬度
        vehicleQueueBO.setCheckinLatitude(0.00D);

        //经度
        vehicleQueueBO.setCheckinLongtitude(0.00D);

        //fix 增加运力平台的车队和ERP车队校验
        vehicleQueueBO.setFleetName(fleetName);

        //推送报班记录到ERP
        erpUtil.pushCheckin(vehicleQueueBO);

        // 报班传送OTM
        IntegrationOtm(driverCheckin.getId(), token);
    }

    private void buildCondition(Map<String, Object> cn, EntityWrapper<DriverCheckinDTO> ew) {
        Object origin = cn.get("departRegion");
        if (origin != null && StringUtils.isNotBlank(origin.toString())) {
            ew.like("depart_region", origin.toString());
        }
        Object destRegion = cn.get("destRegion");
        if (destRegion != null && StringUtils.isNotBlank(destRegion.toString())) {
            ew.like("dest_region", destRegion.toString());
        }
        Object lspName = cn.get("lspName");
        if (lspName != null && StringUtils.isNotBlank(lspName.toString())) {
            ew.eq("lsp_name", lspName.toString());
        }
        Object carrierPlate = cn.get("carrierPlate");
        if (carrierPlate != null && StringUtils.isNotBlank(carrierPlate.toString())) {
            ew.like("carrier_plate", carrierPlate.toString())
                    .eq("carrier_auth_status", TableStatusEnum.STATUS_1.getCode());
        }
        Object trailerPlate = cn.get("trailerPlate");
        if (trailerPlate != null && StringUtils.isNotBlank(trailerPlate.toString())) {
            ew.like("trailer_plate", trailerPlate.toString())
                    .eq("trailer_auth_status", TableStatusEnum.STATUS_1.getCode());
        }
        Object gmtCheckinStart = cn.get("gmtCheckinStart");
        if (gmtCheckinStart != null && StringUtils.isNotBlank(gmtCheckinStart.toString())) {
            ew.ge("gmt_checkin", gmtCheckinStart.toString());
        }
        Object gmtCheckinEnd = cn.get("gmtCheckinEnd");
        if (gmtCheckinEnd != null && StringUtils.isNotBlank(gmtCheckinEnd.toString())) {
            ew.le("gmt_checkin", gmtCheckinEnd.toString());
        }
        Object gmtExpLoadStart = cn.get("gmtExpLoadStart");
        if (gmtExpLoadStart != null && StringUtils.isNotBlank(gmtExpLoadStart.toString())) {
            ew.ge("gmt_exp_load", gmtExpLoadStart.toString());
        }
        Object gmtExpLoadEnd = cn.get("gmtExpLoadEnd");
        if (gmtExpLoadEnd != null && StringUtils.isNotBlank(gmtExpLoadEnd.toString())) {
            ew.le("gmt_exp_load", gmtExpLoadEnd.toString());
        }
        Object checkInStatus = cn.get("checkInStatus");
        if (checkInStatus != null && StringUtils.isNotBlank(checkInStatus.toString())) {
            ew.eq("checkin_status", checkInStatus.toString());
        }
    }


    //启运地、目的地、承运商名称、司机手机、牵引车牌、挂车车牌、报班时间（between）、计划装车时间
    //构建认证承运商查询条件
    private EntityWrapper<DriverCheckinLineBO> buildCondition(Map<String, Object> condition) {
        EntityWrapper<DriverCheckinLineBO> ew = new EntityWrapper<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (!Objects.equals(condition, null)) {
            for (Map.Entry<String, Object> entry : condition.entrySet()) {
                if (!StringUtils.isEmpty(entry.getValue().toString())) {
                    if (entry.getKey().equals("departRegion")) {
                        ew.like("departRegion", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("destRegion")) {
                        ew.like("destRegion", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("driverMobile")) {
                        ew.like("driverMobile", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("lspName")) {
                        ew.eq("lspName", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("lspId")) {
                        ew.eq("lspId", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("carrierPlate")) {
                        ew.like("carrierPlate", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("trailerPlate")) {
                        ew.like("trailerPlate", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("gmtCheckinStart")) {
                        ew.ge("gmtCheckin", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("gmtCheckinEnd")) {
                        ew.le("gmtCheckin", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("gmtExpLoadStart")) {
                        ew.ge("gmtExpLoad", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("gmtExpLoadEnd")) {
                        ew.le("gmtExpLoad", entry.getValue().toString());
                    }
                    if (entry.getKey().equals("checkinStatus")) {
                        ew.eq("checkinStatus", entry.getValue().toString());
                    }
                }
            }
        }
        return ew;
    }

    /**
     * 位置上报
     */
    private void positionUpload(DriverCheckinBO driverCheckinBO) {
        ErpShipToByLicenseVO erpShipToByLicenseVO = new ErpShipToByLicenseVO();
        Long driverId = driverCheckinBO.getDriverId();
        Driver driver = driverService.selectById(driverId);
        if (Objects.isNull(driver)) {
            throw new BaseException("司机信息不存在");
        }
        CarrierInfoBO carrierInfoBO = carrierInfoService.selectByDriverId(driverId);
        String carrierPlate = carrierInfoBO.getPlate();
        if (org.apache.commons.lang3.StringUtils.isBlank(carrierPlate)) {
            throw new BaseException("牵引车车牌号不存在");
        }
        // 车牌号
        erpShipToByLicenseVO.setLicense(carrierPlate);
        // 司机名称
        erpShipToByLicenseVO.setDriverName(driver.getName());
        // 司机电话
        erpShipToByLicenseVO.setMobile(driver.getMobile());
        // 省份
        erpShipToByLicenseVO.setProvince(driverCheckinBO.getProvince());
        // 城市
        erpShipToByLicenseVO.setCity(driverCheckinBO.getCity());

        // 经度
        erpShipToByLicenseVO.setDcx(driverCheckinBO.getCheckinLongtitude());
        // 纬度
        erpShipToByLicenseVO.setDcy(driverCheckinBO.getCheckinLatitude());

        // 详细地址
        erpShipToByLicenseVO.setLocation(driverCheckinBO.getCheckinAddr());

        // 发送在途请求给 erp
        erpUtil.pushLoaction(erpShipToByLicenseVO);
    }

    @Override
    public void driverCheckinToOtm(Long id, String authorization) {

        Map<String,String> map = new HashedMap();
        map.put("id",String.valueOf(id));
        String paramJson = JSONObject.toJSONString(map);
        List<NameValuePair> headNamePairs = Lists.newArrayList();
        headNamePairs.add(new BasicNameValuePair("Authorization", authorization));

        try {
            LOGGER.info("driverInfoToErp info url:{},params:{} ", integrationUrl + checkinToOtmLog, paramJson);
            String driverResult = HttpClientUtil.postJson(integrationUrl + checkinToOtmLog,headNamePairs, paramJson, socketTimeout);
            LOGGER.info("driverInfoToErp result {} ", driverResult);
            if(null == driverResult || "".equals(driverResult)){
                throw new BaseException("获取报班日志错误！");
            }
            RestfulResponse<List<Map<String, Object>>> response = JSONObject.parseObject(driverResult, new TypeReference<RestfulResponse<List<Map<String, Object>>>>() {
            });
            List<Map<String,Object>> logs = new ArrayList<Map<String,Object>>();
            logs = response.getData();
            if(null != response && null != response.getData() && !logs.isEmpty()){
                // 循环判断是否有成功日志，有成功不给推送
                logs.forEach(log ->{
                    if(null != log.get("exportStatus") &&  "success".equals(log.get("exportStatus"))){
                        throw new BaseException("该报班已有推送OTM成功数据！");
                    }
                });
            }

        } catch (Exception e) {
            LOGGER.error("driverInfoToErp url:{},params:{} 连接超时:{}", integrationUrl + checkinToOtmLog, paramJson, e);
            throw new BaseException(e.getMessage());
        }
        IntegrationOtm(id, authorization);
    }

    /**
     * 查询司机报班
     */
    @Override
    public DriverCheckinDTO getDriverCheckinByIdNoTenant(Long id) {
        return baseMapper.getDriverCheckinByIdNoTenant(id);
    }

    @Override
    public Page<DriverCheckinLineVO> otmDriverCheckinLog(Page<DriverCheckinLineBO> page) {

        page.setOrderByField("gmtCheckin");
        page.setAsc(false);
        List<DriverCheckinLineVO> list = baseMapper.getdriverCheckinOtmLog(page,
                buildCondition(page.getCondition()));
        Page<DriverCheckinLineVO> pageVo = new Page<>();
        BeanUtils.copyProperties(page, pageVo);

        pageVo.setRecords(list);
        return pageVo;
    }

    @Override
    public List<DriverCheckin> selectCheckinByLspId(String lspId) {
        return baseMapper.selectCheckinByLspId(lspId);
    }

    @Override
    public List<DriverCheckin> selectCheckinByFleetId(String fleetId) {
        return baseMapper.selectCheckinByFleetId(fleetId);
    }


}
